
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "reflecxx.h"

struct simple_struct {
    int ss_int;
    float ss_float;
    char *ss_string;
};

static int int_array[5];
static struct { int a; float b; } st_array[2];

extern struct reflecxx_full_type simple_struct_type_info;
extern struct reflecxx_full_type int_array_type_info;
extern struct reflecxx_full_type st_array_type_info;

int main(int argc, char *argv[])
{
    int retval = EXIT_SUCCESS;
    
    struct reflecxx_full_type rft;
    struct reflecxx_buffer rb;
    struct reflecxx_error re;
    struct simple_struct *ss;
    reflecxx_primitive_t rp;

    rft.rft_type = RT_INT;
    rb = reflecxx_buffer_string("1234");
    assert(reflecxx_scan(&rb, &rft, &rp, &re) != 0);
    assert(rp.rp_int == 1234);

    rft.rft_type = RT_STRING;
    rb = reflecxx_buffer_string("1234");
    assert(reflecxx_scan(&rb, &rft, &rp, &re) == 0);
    rb = reflecxx_buffer_string("\"1234");
    assert(reflecxx_scan(&rb, &rft, &rp, &re) == 0);
    rb = reflecxx_buffer_string("\"1234\"");
    assert(reflecxx_scan(&rb, &rft, &rp, &re) != 0);
    assert(strcmp("1234", rp.rp_string) == 0);

    rp.rp_pointer = NULL;
    rb = reflecxx_buffer_string("{");
    assert(reflecxx_scan(&rb, &simple_struct_type_info, &rp, &re) == 0);
    rb = reflecxx_buffer_string("{}");
    assert(reflecxx_scan(&rb, &simple_struct_type_info, &rp, &re) != 0);
    ss = rp.rp_pointer;
    assert(ss->ss_int == 0);
    assert(ss->ss_float == 0);

    rb = reflecxx_buffer_string("{ }");
    assert(reflecxx_scan(&rb, &simple_struct_type_info, &rp, &re) != 0);
    rb = reflecxx_buffer_string("{ \"ss_int\" : 4321 }");
    assert(reflecxx_scan(&rb, &simple_struct_type_info, &rp, &re) != 0);
    assert(ss->ss_int == 4321);

    rb = reflecxx_buffer_string("{ \"ss_float\" : 3.14 }");
    assert(reflecxx_scan(&rb, &simple_struct_type_info, &rp, &re) != 0);
    assert(ss->ss_int == 4321);
    assert(ss->ss_float > 3.13);
    assert(ss->ss_float < 3.15);

    rb = reflecxx_buffer_string("{ \"ss_string\" : \"Hello, World!\\n\" }");
    assert(reflecxx_scan(&rb, &simple_struct_type_info, &rp, &re) != 0);
    assert(strcmp(ss->ss_string, "Hello, World!\n") == 0);
    
    rb = reflecxx_buffer_string("{ \"ss_int\" : 54, "
				"  \"ss_string\" : \"Goodbye, World!\\n\" }");
    assert(reflecxx_scan(&rb, &simple_struct_type_info, &rp, &re) != 0);
    assert(ss->ss_int == 54);
    assert(strcmp(ss->ss_string, "Goodbye, World!\n") == 0);

    rb = reflecxx_buffer_string("[0, 1 ,2,3,4,]");
    rp.rp_pointer = int_array;
    assert(reflecxx_scan(&rb, &int_array_type_info, &rp, &re) != 0);
    assert(int_array[0] == 0);
    assert(int_array[1] == 1);
    assert(int_array[2] == 2);
    assert(int_array[3] == 3);
    assert(int_array[4] == 4);
    
    rb = reflecxx_buffer_string("[0, 1 ,2,3,4,5]");
    rp.rp_pointer = int_array;
    assert(reflecxx_scan(&rb, &int_array_type_info, &rp, &re) == 0);
    
    rb = reflecxx_buffer_string("[{\"a\" : 0,\"b\":1.0},{\"a\":6,\"b\":3.1}]");
    rp.rp_pointer = st_array;
    assert(reflecxx_scan(&rb, &st_array_type_info, &rp, &re) != 0);
    assert(st_array[0].a == 0);
    assert(st_array[0].b == 1.0);
    assert(st_array[1].a == 6);
    assert(st_array[1].b == 3.1f);
    
    return retval;
}
